import { Transaction, AlertChannel, AlertMessage, AlertChannelConfig } from '../../types';
import { createModuleLogger } from '../../utils/logger';
import nodemailer from 'nodemailer';
import axios from 'axios';
import config from '../../config';
import { ChainType } from '../../types';

const logger = createModuleLogger('alert-service');

export class AlertService {
  private emailTransporter?: nodemailer.Transporter;

  constructor() {
    this.initializeEmailTransporter();
  }

  // 初始化邮件发送器
  private initializeEmailTransporter(): void {
    if (!config.alerts.email.enabled) {
      logger.info('邮件告警未启用');
      return;
    }

    try {
      this.emailTransporter = nodemailer.createTransport({
        host: config.alerts.email.host,
        port: config.alerts.email.port,
        secure: config.alerts.email.port === 465,
        auth: {
          user: config.alerts.email.user,
          pass: config.alerts.email.password
        }
      });

      logger.info('邮件告警服务已初始化');
    } catch (error) {
      logger.error('初始化邮件服务失败:', error);
    }
  }

  // 发送交易告警
  public async sendTransactionAlert(
    transaction: Transaction,
    channels: AlertChannel[]
  ): Promise<AlertMessage> {
    const alertMessage: AlertMessage = {
      id: `alert_${transaction.id}_${Date.now()}`,
      transaction,
      configId: 'default', // 这里应该传入具体的配置ID
      channels: channels.map(c => c.id),
      sent: false,
      sentAt: undefined,
      error: undefined,
      createdAt: new Date()
    };

    const results: Array<{ channelId: string; success: boolean; error?: string }> = [];

    // 并行发送到所有渠道
    const sendPromises = channels.map(async (channel) => {
      try {
        await this.sendToChannel(transaction, channel);
        results.push({ channelId: channel.id, success: true });
        logger.info(`告警发送成功: ${channel.type} - ${channel.id}`);
      } catch (error) {
        const errorMessage = error instanceof Error ? error.message : '未知错误';
        results.push({ channelId: channel.id, success: false, error: errorMessage });
        logger.error(`告警发送失败: ${channel.type} - ${channel.id}:`, error);
      }
    });

    await Promise.allSettled(sendPromises);

    // 检查是否有任何渠道发送成功
    const hasSuccess = results.some(r => r.success);
    const errors = results.filter(r => !r.success).map(r => r.error).join('; ');

    alertMessage.sent = hasSuccess;
    if (hasSuccess) {
      alertMessage.sentAt = new Date();
    }
    if (errors) {
      alertMessage.error = errors;
    }

    logger.info(`交易告警处理完成: ${transaction.hash}, 成功: ${hasSuccess}`);

    return alertMessage;
  }

  // 发送到指定渠道
  private async sendToChannel(transaction: Transaction, channel: AlertChannel): Promise<void> {
    if (!channel.enabled) {
      throw new Error('告警渠道未启用');
    }

    switch (channel.type) {
      case 'email':
        await this.sendEmailAlert(transaction, channel.config.email!);
        break;
      case 'webhook':
        await this.sendWebhookAlert(transaction, channel.config.webhook!);
        break;
      case 'slack':
        await this.sendSlackAlert(transaction, channel.config.slack!);
        break;
      case 'telegram':
        await this.sendTelegramAlert(transaction, channel.config.telegram!);
        break;
      default:
        throw new Error(`不支持的告警渠道类型: ${channel.type}`);
    }
  }

  // 发送邮件告警
  private async sendEmailAlert(
    transaction: Transaction,
    emailConfig: NonNullable<AlertChannelConfig['email']>
  ): Promise<void> {
    if (!this.emailTransporter) {
      throw new Error('邮件服务未初始化');
    }

    const subject = emailConfig.subject || `链上大额转账告警 - $${transaction.valueUSD.toLocaleString()}`;
    
    const htmlContent = this.generateEmailHTML(transaction);
    const textContent = this.generateEmailText(transaction);

    const mailOptions = {
      from: `ChainWatch <${config.alerts.email.user}>`,
      to: emailConfig.to.join(', '),
      subject,
      text: textContent,
      html: htmlContent
    };

    await this.emailTransporter.sendMail(mailOptions);
  }

  // 发送Webhook告警
  private async sendWebhookAlert(
    transaction: Transaction,
    webhookConfig: NonNullable<AlertChannelConfig['webhook']>
  ): Promise<void> {
    const payload = {
      type: 'large_transaction',
      timestamp: new Date().toISOString(),
      transaction: {
        hash: transaction.hash,
        chain: transaction.chain,
        from: transaction.from,
        to: transaction.to,
        value: transaction.value,
        valueUSD: transaction.valueUSD,
        blockNumber: transaction.blockNumber,
        timestamp: transaction.timestamp.toISOString(),
        tokenSymbol: transaction.tokenSymbol
      }
    };

    const headers = {
      'Content-Type': 'application/json',
      'User-Agent': 'ChainWatch/1.0',
      ...webhookConfig.headers
    };

    await axios.post(webhookConfig.url, payload, { headers, timeout: 10000 });
  }

  // 发送Slack告警
  private async sendSlackAlert(
    transaction: Transaction,
    slackConfig: NonNullable<AlertChannelConfig['slack']>
  ): Promise<void> {
    const message = {
      channel: slackConfig.channel,
      username: 'ChainWatch',
      icon_emoji: ':warning:',
      attachments: [
        {
          color: 'warning',
          title: '🚨 检测到大额转账',
          fields: [
            {
              title: '区块链',
              value: transaction.chain.toUpperCase(),
              short: true
            },
            {
              title: '金额',
              value: `$${transaction.valueUSD.toLocaleString()}${transaction.tokenSymbol ? ` (${transaction.tokenSymbol})` : ''}`,
              short: true
            },
            {
              title: '发送地址',
              value: `\`${transaction.from}\``,
              short: false
            },
            {
              title: '接收地址',
              value: `\`${transaction.to}\``,
              short: false
            },
            {
              title: '交易哈希',
              value: `\`${transaction.hash}\``,
              short: false
            },
            {
              title: '时间',
              value: transaction.timestamp.toLocaleString(),
              short: true
            },
            {
              title: '区块号',
              value: transaction.blockNumber.toString(),
              short: true
            }
          ],
          timestamp: Math.floor(transaction.timestamp.getTime() / 1000)
        }
      ]
    };

    await axios.post(slackConfig.webhookUrl, message, { timeout: 10000 });
  }

  // 发送Telegram告警
  private async sendTelegramAlert(
    transaction: Transaction,
    telegramConfig: NonNullable<AlertChannelConfig['telegram']>
  ): Promise<void> {
    const message = `🚨 *检测到大额转账*

*区块链*: ${transaction.chain.toUpperCase()}
*金额*: $${transaction.valueUSD.toLocaleString()}${transaction.tokenSymbol ? ` (${transaction.tokenSymbol})` : ''}
*发送地址*: \`${transaction.from}\`
*接收地址*: \`${transaction.to}\`
*交易哈希*: \`${transaction.hash}\`
*时间*: ${transaction.timestamp.toLocaleString()}
*区块号*: ${transaction.blockNumber}`;

    const url = `https://api.telegram.org/bot${telegramConfig.botToken}/sendMessage`;
    
    await axios.post(url, {
      chat_id: telegramConfig.chatId,
      text: message,
      parse_mode: 'Markdown',
      disable_web_page_preview: true
    }, { timeout: 10000 });
  }

  // 生成邮件HTML内容
  private generateEmailHTML(transaction: Transaction): string {
    return `
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>ChainWatch 告警</title>
  <style>
    body { font-family: Arial, sans-serif; margin: 0; padding: 20px; background-color: #f5f5f5; }
    .container { max-width: 600px; margin: 0 auto; background-color: white; border-radius: 8px; overflow: hidden; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
    .header { background-color: #ff6b35; color: white; padding: 20px; text-align: center; }
    .content { padding: 30px; }
    .transaction-info { background-color: #f8f9fa; padding: 20px; border-radius: 5px; margin: 20px 0; }
    .info-row { display: flex; justify-content: space-between; margin: 10px 0; }
    .label { font-weight: bold; color: #333; }
    .value { color: #666; word-break: break-all; }
    .amount { font-size: 24px; font-weight: bold; color: #ff6b35; text-align: center; margin: 20px 0; }
    .footer { background-color: #f8f9fa; padding: 20px; text-align: center; color: #666; font-size: 12px; }
  </style>
</head>
<body>
  <div class="container">
    <div class="header">
      <h1>🚨 链上大额转账告警</h1>
    </div>
    <div class="content">
      <div class="amount">
        $${transaction.valueUSD.toLocaleString()}
        ${transaction.tokenSymbol ? `<br><small>(${transaction.tokenSymbol})</small>` : ''}
      </div>
      
      <div class="transaction-info">
        <div class="info-row">
          <span class="label">区块链:</span>
          <span class="value">${transaction.chain.toUpperCase()}</span>
        </div>
        <div class="info-row">
          <span class="label">发送地址:</span>
          <span class="value">${transaction.from}</span>
        </div>
        <div class="info-row">
          <span class="label">接收地址:</span>
          <span class="value">${transaction.to}</span>
        </div>
        <div class="info-row">
          <span class="label">交易哈希:</span>
          <span class="value">${transaction.hash}</span>
        </div>
        <div class="info-row">
          <span class="label">区块号:</span>
          <span class="value">${transaction.blockNumber}</span>
        </div>
        <div class="info-row">
          <span class="label">时间:</span>
          <span class="value">${transaction.timestamp.toLocaleString()}</span>
        </div>
      </div>
      
      <p style="color: #666; text-align: center;">
        此告警由 ChainWatch 监控系统自动发送
      </p>
    </div>
    <div class="footer">
      <p>ChainWatch - 链上大额转账监控平台</p>
      <p>如需取消订阅，请联系管理员</p>
    </div>
  </div>
</body>
</html>`;
  }

  // 生成邮件文本内容
  private generateEmailText(transaction: Transaction): string {
    return `
ChainWatch 链上大额转账告警

检测到大额转账: $${transaction.valueUSD.toLocaleString()}${transaction.tokenSymbol ? ` (${transaction.tokenSymbol})` : ''}

交易详情:
- 区块链: ${transaction.chain.toUpperCase()}
- 发送地址: ${transaction.from}
- 接收地址: ${transaction.to}
- 交易哈希: ${transaction.hash}
- 区块号: ${transaction.blockNumber}
- 时间: ${transaction.timestamp.toLocaleString()}

此告警由 ChainWatch 监控系统自动发送。
`;
  }

  // 测试告警渠道
  public async testChannel(channel: AlertChannel): Promise<{ success: boolean; error?: string }> {
    try {
      const testTransaction: Transaction = {
        id: 'test_transaction',
        hash: '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef',
        chain: ChainType.ETHEREUM,
        from: '0x0000000000000000000000000000000000000001',
        to: '0x0000000000000000000000000000000000000002',
        value: '1000.0',
        valueUSD: 2000000,
        blockNumber: 18000000,
        timestamp: new Date(),
        confirmed: true
      };

      await this.sendToChannel(testTransaction, channel);
      return { success: true };
    } catch (error) {
      const errorMessage = error instanceof Error ? error.message : '未知错误';
      logger.error(`测试告警渠道失败: ${channel.type} - ${channel.id}:`, error);
      return { success: false, error: errorMessage };
    }
  }
} 